package ru.spbsu.electromenu.serialization.json;

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.spbsu.electromenu.model.*;
import ru.spbsu.electromenu.serialization.SerializationException;
import ru.spbsu.electromenu.serialization.Serializer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Date: 3/22/11
 * Time: 7:31 PM
 *
 * @author Artem Titov
 */
public class JSONSerializer implements Serializer {
    private static final Logger logger = LoggerFactory.getLogger(JSONSerializer.class);

    private JSONObject dishToJSONObject(final Dish dish) {
        final Map<String, String> fields = new HashMap<String, String>(7, 1);
        fields.put("id", String.valueOf(dish.getId()));
        fields.put("name", dish.getName());
        fields.put("description", dish.getDescription());
        fields.put("price", String.valueOf(dish.getPrice()));
        fields.put("picture", dish.getImage());
        fields.put("tag-id", String.valueOf(dish.getTagId()));
        fields.put("available", String.valueOf((dish.isAvailable()) ? 1 : 0));
        return new JSONObject(fields);
    }

    private JSONObject tagToJSONObject(final Tag tag) {
        final Map<String, String> fields = new HashMap<String, String>(2, 1);
        fields.put("id", String.valueOf(tag.getId()));
        fields.put("name", tag.getName());
        return new JSONObject(fields);
    }

    @Override
    public String serializeDish(final Dish dish) throws SerializationException {
        if (dish == null) {
            throw new SerializationException("Can't serialize null data");
        }
        final String result = dishToJSONObject(dish).toString();
        logger.debug("Dish serialized to: {}", result);
        return result;
    }

    @Override
    public String serializeTag(final Tag tag) throws SerializationException {
        if (tag == null) {
            throw new SerializationException("Can't serialize null data");
        }
        final String result = tagToJSONObject(tag).toString();
        logger.debug("Tag serialized to: {}", result);
        return result;
    }

    @Override
    public String serializeMenu(final List<Dish> dishes, final List<Tag> tags, final List<Table> tables) throws SerializationException {
        if (dishes == null || tags == null || tables == null) {
            throw new SerializationException("Can't serialize null data");
        }
        final List<JSONObject> dishesJSON = new ArrayList<JSONObject>(dishes.size());
        for (final Dish dish : dishes) {
            dishesJSON.add(dishToJSONObject(dish));
        }
        final List<JSONObject> tagsJSON = new ArrayList<JSONObject>(tags.size());
        for (final Tag tag : tags) {
            tagsJSON.add(tagToJSONObject(tag));
        }
        final List<String> tablesJSON = new ArrayList<String>(tables.size());
        for (final Table table : tables) {
            tablesJSON.add(String.valueOf(table.getId()));
        }
        final Map<String, Object> fields = new HashMap<String, Object>(3, 1);
        fields.put("dishes", dishesJSON);
        fields.put("tables", tablesJSON);
        fields.put("tags", tagsJSON);
        final String result = new JSONObject(fields).toString();
        logger.debug("Menu serialized to: {}", result);
        return result;
    }

    @Override
    public String serializeSession(final Session session) throws SerializationException {
        if (session == null) {
            throw new SerializationException("Can't serialize null data");
        }
        final Map<String, String> fields = new HashMap<String, String>(2, 1);
        fields.put("session-id", String.valueOf(session.getId()));
        fields.put("table-id", String.valueOf(session.getTableId()));
        final String result = new JSONObject(fields).toString();
        logger.debug("Session serialized to: {}", result);
        return result;
    }

    @Override
    public String serializeOrder(final Order order) throws SerializationException {
        if (order == null) {
            throw new SerializationException("Can't serialize null data");
        }
        final Map<String, String> fields = new HashMap<String, String>(1, 1);
        fields.put("id", String.valueOf(order.getId()));
        final String result = new JSONObject(fields).toString();
        logger.debug("Order serialized to: {}", result);
        return result;
    }
}
